package com.chuangke.security.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.chuangke.common.utils.IpUtils;
import com.chuangke.security.userdetails.JwtUserDetails;

import cn.hutool.core.lang.UUID;
import eu.bitwalker.useragentutils.UserAgent;

public interface JwtTokenManager {

	// 令牌前缀
	String LOGIN_USER_KEY = "login_user_key";

	// 登录用户 redis key
	String LOGIN_TOKEN_KEY = "login_tokens:";

	long ONE_MINUTE = 60 * 1000;

	/**
	 * 生成令牌
	 *
	 * @param authentication 用户
	 * @return 令牌
	 */
	default String generateToken(Authentication authentication) {
		JwtUserDetails loginUser = (JwtUserDetails) authentication.getPrincipal();

		String uuid = UUID.fastUUID().toString();
		loginUser.setUuid(uuid);
		loginUser.setLoginTime(System.currentTimeMillis());
		setUserAgent(loginUser);
		refreshToken(loginUser);

		Map<String, String> claims = new HashMap<>();
		claims.put(LOGIN_USER_KEY, uuid);
		return generateToken(claims);
	}

	/**
	 * 设置用户代理信息
	 *
	 * @param loginUser 登录信息
	 */
	default void setUserAgent(JwtUserDetails loginUser) {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
		String ip = IpUtils.getIpAddr(request);
		loginUser.setIpaddr(ip);
		loginUser.setBrowser(userAgent.getBrowser().getName());
		loginUser.setOs(userAgent.getOperatingSystem().getName());
	}

	/**
	 * 验证令牌有效期，相差不足20分钟，自动刷新缓存
	 *
	 * @param loginUser
	 * @return 令牌
	 */
	void verifyToken(JwtUserDetails loginUser);

	/**
	 * 刷新令牌有效期
	 *
	 * @param loginUser 登录信息
	 */
	void refreshToken(JwtUserDetails loginUser);

	/**
	 * 获取用户身份信息
	 */
	JwtUserDetails getLoginUser(HttpServletRequest request);

	/**
	 * 删除用户身份信息
	 */
	void delLoginUser(String userUuid);

	/**
	 * 获取username对应其他的所有登录uuid，不包含对当前的登录信息
	 *
	 * @param username
	 * @param currentToken
	 * @return
	 */
	List<String> getOtherLoginUuid(String username, String currentToken);

	List<JwtUserDetails> listOnlineUser();

	/**
	 * 判断令牌是否过期
	 *
	 * @param token 令牌
	 * @return 是否过期
	 */
	Boolean isTokenExpired(String token);

	/**
	 * 获取请求token
	 *
	 * @param request
	 * @return
	 */
	String getToken(HttpServletRequest request);

	String generateToken(String userLoginKey, Date expirationDate);

	/**
	 * 从数据声明生成令牌
	 *
	 * @param claims 数据声明
	 * @return 令牌
	 */
	String generateToken(Map<String, String> claims);

}